#encoding:utf8
#auth: mavarick
#date: {DATETIME}

import copy
import os
import sys
import tornado.ioloop
import tornado.web
import hashlib
import requests
import logging
import json
import time

logging.basicConfig(level=logging.WARNING,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
logger = logging.getLogger("file.downloader")
logger.setLevel(logging.INFO)
# logger.propagate = True

# change the PORT
PORT = 9001

# change the DATA PATH
BASE_PATH = "./data"


return_data = dict(code=0, data="")


class FileDownloader(object):
    def __init__(self, base_path):
        self.base_path = base_path
        self.check_path(base_path)

    def check_path(self, base_path):
        if not os.path.exists(base_path):
            logger.warning("base path [%s] does not exists and create ..." % base_path)
            os.makedirs(base_path)
        if os.path.isfile(base_path):
            logger.error("base path [%s] exists and is file" % base_path)

    def download(self, url):
        try:
            st = time.time()
            self._check_url(url)
            filename = self.get_filename(url)
            _f, type = self.get_file_type(filename)
            id = self.get_id(url)
            size = self.get_size(url)
            local_file = os.path.join(self.base_path, "%s%s"%(id, type))
            logger.info("download [%s] -> [%s]" % (url, local_file))
            self._download(url, local_file)
            et = time.time()
            data = dict(url=url, filename=filename, size=size, type=type, path=local_file, time_used=et - st)
            return 0, data
        except EmptyValue, ex:
            return -1, ex.message

    def _check_url(self, url):
        if not url:
            raise EmptyValue("url is empty")

    def get_filename(self, url):
        return url.split('/')[-1]

    def get_id(self, url):
        return hashlib.md5(url).hexdigest()

    def get_size(self, url):
        try:
            r = requests.head(url)
            file_size = int(r.headers['content-length'])
            return file_size
        except:
            return -1

    def get_file_type(self, filename):
        name, ext = os.path.splitext(filename)
        return name, ext

    def _download(self, url, local_filename):
        r = requests.get(url, stream=True)
        with open(local_filename, 'wb') as f:
            for chunk in r.iter_content(chunk_size=1024):
                if chunk:  # filter out keep-alive new chunks
                    f.write(chunk)
                    # f.flush() commented by recommendation from J.F.Sebastian
        return local_filename


class EmptyValue(Exception):
    pass


downloader = FileDownloader(base_path=BASE_PATH)


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        ret = copy.copy(return_data)
        url = self.get_argument("url", "")
        if not url:
            ret.update(dict(code=-1, data="no url"))
        else:
            code, data = downloader.download(url)
            ret.update(dict(code=code, data=data))

        self.set_header("Content-Type", "application/json")
        content = json.dumps(ret)
        self.write(content)

    def post(self, *args, **kwargs):
        self.get()


application = tornado.web.Application([
    (r"/", MainHandler),
])


# test: http://localhost:9001/?url=https://public.lightpic.info/image/E49E_59AD58D70.jpg
if __name__ == "__main__":
    logger.info("start server, with port: [%s]" % PORT)
    application.listen(PORT)
    tornado.ioloop.IOLoop.instance().start()
